﻿using CCL.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CCL.SocketMessage;

namespace CCL.TableStructure
{
    /// <summary>
    /// 직렬화 가능한 Database의 User Table을 제공합니다.
    /// </summary>
    public class User : Table, ISerializable
    {
        /// <summary>
        /// 해당 User의 고유한 ID값을 가져옵니다.
        /// </summary>
        public int UserID { get; private set; }

        /// <summary>
        /// 해당 User의 이름을 가져옵니다.
        /// </summary>
        public char[] Name { get; private set; }
        
        /// <summary>
        /// 해당 User의 E-Mail을 가져옵니다.
        /// </summary>
        public char[] Email { get; private set; }
        
        /// <summary>
        /// 해당 User의 Password를 가져옵니다.
        /// </summary>
        public char[] Password { get; private set; }
        
        /// <summary>
        /// 해당 User가 가입한 날짜를 가져옵니다.
        /// </summary>
        public char[] JoinedDate { get; private set; }

        /// <summary>
        /// 해당 Table의 총 Size
        /// </summary>
        public new const int TableSize =
                sizeof(int) +                   // UserID
                Constant.Length.Name +          // Name
                Constant.Length.Email +         // Email
                Constant.Length.Password +      // Password
                Constant.Length.Date;           // JoinedDate

        /// <summary>
        /// 새로운 User Table 객체를 생성합니다.
        /// </summary>
        /// <param name="bytes">직렬화된 byte 배열</param>
        public User(byte[] bytes)
        {
            int startidx = 0;

            UserID = BitConverter.ToInt32(bytes, startidx);
            startidx += sizeof(uint);

            Name = new char[Constant.Length.Name];
            Encoding.Default.GetChars(bytes, startidx, Constant.Length.Name, Name, 0);
            startidx += Constant.Length.Name;

            Email = new char[Constant.Length.Email];
            Encoding.Default.GetChars(bytes, startidx, Constant.Length.Email, Email, 0);
            startidx += Constant.Length.Email;

            Password = new char[Constant.Length.Password];
            Encoding.Default.GetChars(bytes, startidx, Constant.Length.Password, Password, 0);
            startidx += Constant.Length.Password;

            JoinedDate = new char[Constant.Length.Date];
            Encoding.Default.GetChars(bytes, startidx, Constant.Length.Date, JoinedDate, 0);
        }

        /// <summary>
        /// 새로운 User Table 객체를 생성합니다.
        /// </summary>
        /// <param name="userID">해당 User의 고유 ID</param>
        /// <param name="name">해당 User의 이름</param>
        /// <param name="email">해당 User의 E-Mail 주소</param>
        /// <param name="password">해당 User의 Password</param>
        /// <param name="dateTime">해당 User가 가입한 날짜</param>
        public User(int userID, string name, string email, string password, DateTime dateTime)
        {
            UserID = userID;
            Name = StringUtility.StringCopy(name, Constant.Length.Name);
            Email = StringUtility.StringCopy(email, Constant.Length.Email);
            Password = StringUtility.StringCopy(password, Constant.Length.Password);
            JoinedDate = StringUtility.StringCopy(dateTime.ToString(), Constant.Length.Date);
        }

        /// <summary>
        /// 바이트 배열로 직렬화 합니다.
        /// </summary>
        /// <returns>직렬화된 바이트 배열</returns>
        public byte[] GetByte()
        {
            byte[] bytes = new byte[GetSize()];

            int destIndex = 0;
            byte[] temp;

            temp = BitConverter.GetBytes(UserID);
            Array.Copy(temp, 0, bytes, destIndex, temp.Length);
            destIndex += temp.Length;

            temp = Encoding.Default.GetBytes(Name);
            Array.Copy(temp, 0, bytes, destIndex, Constant.Length.Name);
            destIndex += Constant.Length.Name;

            temp = Encoding.Default.GetBytes(Email);
            Array.Copy(temp, 0, bytes, destIndex, Constant.Length.Email);
            destIndex += Constant.Length.Email;

            temp = Encoding.Default.GetBytes(Password);
            Array.Copy(temp, 0, bytes, destIndex, Constant.Length.Password);
            destIndex += Constant.Length.Password;

            temp = Encoding.Default.GetBytes(JoinedDate);
            Array.Copy(temp, 0, bytes, destIndex, Constant.Length.Date);

            return bytes;
        }

        /// <summary>
        /// 직렬화 가능한 객체의 바이트 사이즈를 가져옵니다.
        /// </summary>
        /// <returns>직렬화된 바이트 사이즈</returns>
        public uint GetSize()
        {
            return TableSize;
        }
    }
}
